import time
import context

// This example demonstrates the use of a cancelable context to prevent a
// routine leak. By the end of the example function, the routine started
// by gen will return without leaking.
fn main() {
    // gen generates integers in a separate routine and
    // sends them to the returned channel.
    // The callers of gen need to cancel the context once
    // they are done consuming generated integers not to leak
    // the internal routine started by gen.
    gen := fn (mut ctx context.Context) chan int {
        dst := chan int{}
        go fn (mut ctx context.Context, dst chan int) {
            mut v := 0
            ch := ctx.done()
            for {
                select {
                    _ := <-ch {
                        // returning not to leak the routine
                        eprintln('> go thread returns because ctx was canceled/done')
                        return
                    }
                    dst <- v {
                        v++
                    }
                }
            }
        }(mut ctx, dst)
        return dst
    }

    mut background := context.background()
    mut ctx, cancel := context.with_cancel(mut &background)
    defer {
        cancel()
        time.sleep(2 * time.millisecond) // give a small time window, in which the go thread routine has a chance to return
    }

    mut mut_ctx := ctx
    mut ctx2 := &mut_ctx
    ch := gen(mut ctx2)
	// ch := gen(mut mut_ctx)
	// ch := gen(mut ctx)
    for i in 0 .. 5 {
        v := <-ch
        println('> received value: $v')
        assert i == v
    }
    println('> main is finished here')
}
